#define _CRT_SECURE_NO_WARNINGS
#include <SDL2/SDL.h>
#include <stdbool.h>
#include <math.h>
#include <string.h>
#include <windows.h>
#include <imm.h>
#include <shlwapi.h>
#include <locale.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb_image_write.h"



#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
#define EDGE_SNAP_RANGE 100
#define EDGE_WIDTH 2
#define HANDLE_SIZE 8
#define MARK_COLOR_R 255
#define MARK_COLOR_G 0
#define MARK_COLOR_B 0
#define MARK_BORDER_WIDTH 2

typedef struct {
    int left, right;
    int top, bottom;
    int dragging_edge;
} CropBorders;

typedef struct {
    SDL_Rect rect;
} MarkedArea;

typedef struct {
    SDL_Texture* texture;
    int width, height;
    float scale_factor;
    SDL_Rect img_dst_rect;
    
    CropBorders crop_borders;
    bool show_crop_edges;
    bool lock_crop_display;
    
    struct {
        bool dragging_rect;
        SDL_Point start;
        SDL_Point current;
    } rect_select;
    
    unsigned char* image_data;
    bool ctrl_pressed;
    bool is_fullscreen;
    char current_file[MAX_PATH];
    char current_dir[MAX_PATH];
    char** file_list;
    int file_count;
    int current_index;
    bool modified;
    
    float zoom_factor;
    SDL_Point view_offset;
    bool is_dragging_view;
    SDL_Point drag_start;
    
    MarkedArea* marked_areas;
    int marked_area_count;
    struct {
        bool is_marking;
        SDL_Point start;
        SDL_Point current;
    } mark_select;
} AppState;

void get_dir_and_base(const char* path, char* dir, char* base);
SDL_Point image_to_screen(AppState* state, int img_x, int img_y);
SDL_Point screen_to_image(AppState* state, int screen_x, int screen_y);
void calculate_image_position(AppState* state, SDL_Window* window);
void rotate_image(AppState* state, SDL_Renderer* renderer, int angle);
void load_file_list(AppState* state);
SDL_Texture* load_image(SDL_Renderer* renderer, const char* path, int* w, int* h, unsigned char** data);
void save_cropped_image(AppState* state, const char* filename, SDL_Renderer* renderer, SDL_Window* window, bool with_marks);
void render_crop_edges(SDL_Renderer* renderer, AppState* state);
void render_marked_areas(SDL_Renderer* renderer, AppState* state);
char* show_file_dialog(BOOL save);
void handle_mouse(SDL_Event* e, AppState* state, SDL_Window* window);
void toggle_fullscreen(SDL_Window* window, AppState* state);
void load_current_image(AppState* state, SDL_Renderer* renderer, SDL_Window* window);
void load_next_image(AppState* state, SDL_Renderer* renderer, SDL_Window* window, int direction);
void transform_marked_areas(AppState* state, int angle);
void clear_marked_areas(AppState* state);

void get_dir_and_base(const char* path, char* dir, char* base) {
    char drive[_MAX_DRIVE];
    char dir_part[_MAX_DIR];
    char fname[_MAX_FNAME];
    char ext[_MAX_EXT];
    _splitpath(path, drive, dir_part, fname, ext);
    
    if (dir) sprintf(dir, "%s%s", drive, dir_part);
    if (base) sprintf(base, "%s%s", fname, ext);
}

SDL_Point image_to_screen(AppState* state, int img_x, int img_y) {
    float screen_x = state->img_dst_rect.x + 
                   (img_x * state->scale_factor * state->zoom_factor) + 
                   state->view_offset.x;
    float screen_y = state->img_dst_rect.y + 
                   (img_y * state->scale_factor * state->zoom_factor) + 
                   state->view_offset.y;
    return (SDL_Point){
        (int)roundf(screen_x),
        (int)roundf(screen_y)
    };
}

SDL_Point screen_to_image(AppState* state, int screen_x, int screen_y) {
    return (SDL_Point){
        (int)((screen_x - state->img_dst_rect.x - state->view_offset.x) / (state->scale_factor * state->zoom_factor)),
        (int)((screen_y - state->img_dst_rect.y - state->view_offset.y) / (state->scale_factor * state->zoom_factor))
    };
}

void calculate_image_position(AppState* state, SDL_Window* window) {
    int render_w, render_h;
    int logical_w, logical_h;
    
    SDL_GL_GetDrawableSize(window, &render_w, &render_h);
    SDL_GetWindowSize(window, &logical_w, &logical_h);
    
    float dpi_scale_x = (float)render_w / logical_w;
    float dpi_scale_y = (float)render_h / logical_h;
    
    float base_scale = fminf(
        (logical_w / dpi_scale_x) / state->width,
        (logical_h / dpi_scale_y) / state->height
    );
    
    state->scale_factor = base_scale * dpi_scale_x;
    
    state->img_dst_rect.w = (int)(state->width * state->scale_factor * state->zoom_factor);
    state->img_dst_rect.h = (int)(state->height * state->scale_factor * state->zoom_factor);
    
    state->img_dst_rect.x = (render_w - state->img_dst_rect.w) / 2;
    state->img_dst_rect.y = (render_h - state->img_dst_rect.h) / 2;
    
    float offset_ratio_x = (state->view_offset.x + (render_w - state->img_dst_rect.w)/2.0f) / render_w;
    float offset_ratio_y = (state->view_offset.y + (render_h - state->img_dst_rect.h)/2.0f) / render_h;
    
    state->view_offset.x = offset_ratio_x * render_w - (render_w - state->img_dst_rect.w)/2.0f;
    state->view_offset.y = offset_ratio_y * render_h - (render_h - state->img_dst_rect.h)/2.0f;
}

void transform_marked_areas(AppState* state, int angle) {
    for (int i = 0; i < state->marked_area_count; i++) {
        SDL_Rect original = state->marked_areas[i].rect;
        SDL_Rect transformed = {0};
        
        switch (angle) {
            case 90:
                transformed.x = state->height - original.y - original.h;
                transformed.y = original.x;
                transformed.w = original.h;
                transformed.h = original.w;
                break;
            case 180:
                transformed.x = state->width - original.x - original.w;
                transformed.y = state->height - original.y - original.h;
                transformed.w = original.w;
                transformed.h = original.h;
                break;
            case 270:
                transformed.x = original.y;
                transformed.y = state->width - original.x - original.w;
                transformed.w = original.h;
                transformed.h = original.w;
                break;
            default:
                transformed = original;
                break;
        }
        
        transformed.x = SDL_clamp(transformed.x, 0, state->width - 1);
        transformed.y = SDL_clamp(transformed.y, 0, state->height - 1);
        transformed.w = SDL_clamp(transformed.w, 1, state->width - transformed.x);
        transformed.h = SDL_clamp(transformed.h, 1, state->height - transformed.y);
        
        state->marked_areas[i].rect = transformed;
    }
}

void rotate_image(AppState* state, SDL_Renderer* renderer, int angle) {
    if (!state->image_data) return;
    
    int new_width = (angle % 180 == 0) ? state->width : state->height;
    int new_height = (angle % 180 == 0) ? state->height : state->width;
    
    unsigned char* rotated = (unsigned char*)malloc(new_width * new_height * 4);
    
    for (int y = 0; y < state->height; y++) {
        for (int x = 0; x < state->width; x++) {
            int new_x, new_y;
            
            switch (angle) {
                case 90:
                    new_x = state->height - 1 - y;
                    new_y = x;
                    break;
                case 180:
                    new_x = state->width - 1 - x;
                    new_y = state->height - 1 - y;
                    break;
                case 270:
                    new_x = y;
                    new_y = state->width - 1 - x;
                    break;
                default:
                    new_x = x;
                    new_y = y;
                    break;
            }
            
            for (int c = 0; c < 4; c++) {
                rotated[(new_y * new_width + new_x) * 4 + c] = 
                    state->image_data[(y * state->width + x) * 4 + c];
            }
        }
    }
    
    free(state->image_data);
    state->image_data = rotated;
    state->width = new_width;
    state->height = new_height;
    state->modified = true;
    
    if (state->show_crop_edges) {
        int old_left = state->crop_borders.left;
        int old_right = state->crop_borders.right;
        int old_top = state->crop_borders.top;
        int old_bottom = state->crop_borders.bottom;
        
        switch (angle) {
            case 90:
                state->crop_borders.left = old_top;
                state->crop_borders.right = old_bottom;
                state->crop_borders.top = new_width - old_right;
                state->crop_borders.bottom = new_width - old_left;
                break;
            case 180:
                state->crop_borders.left = new_width - old_right;
                state->crop_borders.right = new_width - old_left;
                state->crop_borders.top = new_height - old_bottom;
                state->crop_borders.bottom = new_height - old_top;
                break;
            case 270:
                state->crop_borders.left = new_height - old_bottom;
                state->crop_borders.right = new_height - old_top;
                state->crop_borders.top = old_left;
                state->crop_borders.bottom = old_right;
                break;
        }
        
        state->crop_borders.left = SDL_clamp(state->crop_borders.left, 0, state->width-1);
        state->crop_borders.right = SDL_clamp(state->crop_borders.right, state->crop_borders.left+1, state->width);
        state->crop_borders.top = SDL_clamp(state->crop_borders.top, 0, state->height-1);
        state->crop_borders.bottom = SDL_clamp(state->crop_borders.bottom, state->crop_borders.top+1, state->height);
    }
    
    transform_marked_areas(state, angle);
    
    SDL_DestroyTexture(state->texture);
    state->texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, 
                                      SDL_TEXTUREACCESS_STATIC, 
                                      state->width, state->height);
    SDL_UpdateTexture(state->texture, NULL, state->image_data, state->width * 4);
    
    if (!state->lock_crop_display) {
        state->show_crop_edges = true;
    }
}

void clear_marked_areas(AppState* state) {
    if (state->marked_areas) {
        free(state->marked_areas);
        state->marked_areas = NULL;
        state->marked_area_count = 0;
    }
}

void load_file_list(AppState* state) {
    if (state->file_list) {
        for (int i = 0; i < state->file_count; i++) {
            free(state->file_list[i]);
        }
        free(state->file_list);
        state->file_list = NULL;
    }
    
    WIN32_FIND_DATAA ffd;
    HANDLE hFind = INVALID_HANDLE_VALUE;
    char searchPath[MAX_PATH];
    
    sprintf(searchPath, "%s\\*.*", state->current_dir);
    
    hFind = FindFirstFileA(searchPath, &ffd);
    if (hFind == INVALID_HANDLE_VALUE) return;
    
    state->file_count = 0;
    do {
        if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            const char* ext = PathFindExtensionA(ffd.cFileName);
            if (strcmpi(ext, ".png") == 0 || strcmpi(ext, ".jpg") == 0 ||
                strcmpi(ext, ".jpeg") == 0 || strcmpi(ext, ".bmp") == 0) {
                state->file_count++;
            }
        }
    } while (FindNextFileA(hFind, &ffd) != 0);
    
    FindClose(hFind);
    
    state->file_list = (char**)malloc(state->file_count * sizeof(char*));
    int index = 0;
    hFind = FindFirstFileA(searchPath, &ffd);
    do {
        if (!(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) {
            const char* ext = PathFindExtensionA(ffd.cFileName);
            if (strcmpi(ext, ".png") == 0 || strcmpi(ext, ".jpg") == 0 ||
                strcmpi(ext, ".jpeg") == 0 || strcmpi(ext, ".bmp") == 0) {
                state->file_list[index] = _strdup(ffd.cFileName);
                index++;
            }
        }
    } while (FindNextFileA(hFind, &ffd) != 0);
    FindClose(hFind);
    
    char current_base[MAX_PATH];
    get_dir_and_base(state->current_file, NULL, current_base);
    for (int i = 0; i < state->file_count; i++) {
        if (strcmp(state->file_list[i], current_base) == 0) {
            state->current_index = i;
            break;
        }
    }
}

SDL_Texture* load_image(SDL_Renderer* renderer, const char* path, int* w, int* h, unsigned char** data) {
    *data = stbi_load(path, w, h, NULL, 4);
    if (!*data) {
        fprintf(stderr, "Failed to load image: %s\n", stbi_failure_reason());
        return NULL;
    }

    SDL_Texture* tex = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_RGBA32, 
                                       SDL_TEXTUREACCESS_STATIC, *w, *h);
    if (!tex) {
        fprintf(stderr, "Texture creation failed: %s\n", SDL_GetError());
        stbi_image_free(*data);
        return NULL;
    }

    SDL_SetTextureScaleMode(tex, SDL_ScaleModeBest);
    SDL_UpdateTexture(tex, NULL, *data, *w * 4);
    return tex;
}

void save_cropped_image(AppState* state, const char* filename, SDL_Renderer* renderer, SDL_Window* window, bool with_marks) {
    if (!state->image_data) return;
    
    int left = state->show_crop_edges ? state->crop_borders.left : 0;
    int right = state->show_crop_edges ? state->crop_borders.right : state->width;
    int top = state->show_crop_edges ? state->crop_borders.top : 0;
    int bottom = state->show_crop_edges ? state->crop_borders.bottom : state->height;

    int w = right - left;
    int h = bottom - top;
    if (w <= 0 || h <= 0) return;

    unsigned char* cropped = (unsigned char*)malloc(w * h * 4);
    for (int y = 0; y < h; y++) {
        memcpy(&cropped[y * w * 4], 
              &state->image_data[((y + top) * state->width + left) * 4],
              w * 4);
    }

    if (with_marks && state->marked_area_count > 0) {
        for (int i = 0; i < state->marked_area_count; i++) {
            MarkedArea area = state->marked_areas[i];
            
            SDL_Rect crop_relative_rect = {
                area.rect.x - left,
                area.rect.y - top,
                area.rect.w,
                area.rect.h
            };
            
            if (crop_relative_rect.x >= 0 && 
                crop_relative_rect.y >= 0 &&
                (crop_relative_rect.x + crop_relative_rect.w) <= w &&
                (crop_relative_rect.y + crop_relative_rect.h) <= h) 
            {
                // 绘制上边框
                for (int y = crop_relative_rect.y; 
                     y < crop_relative_rect.y + MARK_BORDER_WIDTH && y < h; 
                     y++) 
                {
                    for (int x = crop_relative_rect.x; 
                         x < crop_relative_rect.x + crop_relative_rect.w && x < w; 
                         x++) 
                    {
                        int idx = (y * w + x) * 4;
                        cropped[idx] = MARK_COLOR_R;
                        cropped[idx+1] = MARK_COLOR_G;
                        cropped[idx+2] = MARK_COLOR_B;
                    }
                }
                
                // 绘制下边框
                for (int y = SDL_max(crop_relative_rect.y + crop_relative_rect.h - MARK_BORDER_WIDTH, 0);
                     y < crop_relative_rect.y + crop_relative_rect.h && y < h;
                     y++)
                {
                    for (int x = crop_relative_rect.x;
                         x < crop_relative_rect.x + crop_relative_rect.w && x < w;
                         x++)
                    {
                        int idx = (y * w + x) * 4;
                        cropped[idx] = MARK_COLOR_R;
                        cropped[idx+1] = MARK_COLOR_G;
                        cropped[idx+2] = MARK_COLOR_B;
                    }
                }
                
                // 绘制左边框
                for (int x = crop_relative_rect.x;
                     x < crop_relative_rect.x + MARK_BORDER_WIDTH && x < w;
                     x++)
                {
                    for (int y = crop_relative_rect.y;
                         y < crop_relative_rect.y + crop_relative_rect.h && y < h;
                         y++)
                    {
                        int idx = (y * w + x) * 4;
                        cropped[idx] = MARK_COLOR_R;
                        cropped[idx+1] = MARK_COLOR_G;
                        cropped[idx+2] = MARK_COLOR_B;
                    }
                }
                
                // 绘制右边框
                for (int x = SDL_max(crop_relative_rect.x + crop_relative_rect.w - MARK_BORDER_WIDTH, 0);
                     x < crop_relative_rect.x + crop_relative_rect.w && x < w;
                     x++)
                {
                    for (int y = crop_relative_rect.y;
                         y < crop_relative_rect.y + crop_relative_rect.h && y < h;
                         y++)
                    {
                        int idx = (y * w + x) * 4;
                        cropped[idx] = MARK_COLOR_R;
                        cropped[idx+1] = MARK_COLOR_G;
                        cropped[idx+2] = MARK_COLOR_B;
                    }
                }
            }
        }
    }

    stbi_write_png(filename, w, h, 4, cropped, w * 4);
    free(cropped);
    state->modified = false;
    
    load_file_list(state);
    load_current_image(state, renderer, window);
}

void render_crop_edges(SDL_Renderer* renderer, AppState* state) {
    if (!state->show_crop_edges) return;
    
    SDL_Point top_left = image_to_screen(state, state->crop_borders.left, state->crop_borders.top);
    SDL_Point top_right = image_to_screen(state, state->crop_borders.right, state->crop_borders.top);
    SDL_Point bottom_left = image_to_screen(state, state->crop_borders.left, state->crop_borders.bottom);
    SDL_Point bottom_right = image_to_screen(state, state->crop_borders.right, state->crop_borders.bottom);

    SDL_Rect edges[] = {
        {top_left.x, top_left.y, EDGE_WIDTH, bottom_left.y - top_left.y},
        {top_right.x - EDGE_WIDTH, top_right.y, EDGE_WIDTH, bottom_right.y - top_right.y},
        {top_left.x, top_left.y, top_right.x - top_left.x, EDGE_WIDTH},
        {bottom_left.x, bottom_left.y - EDGE_WIDTH, bottom_right.x - bottom_left.x, EDGE_WIDTH}
    };

    for (int i = 0; i < 4; i++) {
        SDL_SetRenderDrawColor(renderer, 80, 220, 80, 
                             (state->crop_borders.dragging_edge == i+1) ? 255 : 180);
        SDL_RenderFillRect(renderer, &edges[i]);
    }

    SDL_Rect corners[] = {
        {top_left.x - HANDLE_SIZE/2, top_left.y - HANDLE_SIZE/2, HANDLE_SIZE, HANDLE_SIZE},
        {top_right.x - HANDLE_SIZE/2, top_right.y - HANDLE_SIZE/2, HANDLE_SIZE, HANDLE_SIZE},
        {bottom_left.x - HANDLE_SIZE/2, bottom_left.y - HANDLE_SIZE/2, HANDLE_SIZE, HANDLE_SIZE},
        {bottom_right.x - HANDLE_SIZE/2, bottom_right.y - HANDLE_SIZE/2, HANDLE_SIZE, HANDLE_SIZE}
    };
    SDL_SetRenderDrawColor(renderer, 220, 80, 80, 200);
    for (int i = 0; i < 4; i++) {
        SDL_RenderFillRect(renderer, &corners[i]);
    }
}

void render_marked_areas(SDL_Renderer* renderer, AppState* state) {
    SDL_SetRenderDrawBlendMode(renderer, SDL_BLENDMODE_BLEND);
    SDL_SetRenderDrawColor(renderer, MARK_COLOR_R, MARK_COLOR_G, MARK_COLOR_B, 255);
    
    for (int i = 0; i < state->marked_area_count; i++) {
        MarkedArea area = state->marked_areas[i];
        SDL_Point top_left = image_to_screen(state, area.rect.x, area.rect.y);
        SDL_Point bottom_right = image_to_screen(state, 
            area.rect.x + area.rect.w, 
            area.rect.y + area.rect.h);
        
        const float line_width = fmaxf(1.0f, 1.0f / state->zoom_factor);
        const SDL_FRect rects[] = {
            { top_left.x, top_left.y, (float)(bottom_right.x - top_left.x), line_width }, // 上边
            { top_left.x, bottom_right.y - line_width, (float)(bottom_right.x - top_left.x), line_width }, // 下边
            { top_left.x, top_left.y, line_width, (float)(bottom_right.y - top_left.y) }, // 左边
            { bottom_right.x - line_width, top_left.y, line_width, (float)(bottom_right.y - top_left.y) } // 右边
        };
        
        for (int j = 0; j < 4; j++) {
            SDL_RenderFillRectF(renderer, &rects[j]);
        }
    }
    
    if (state->mark_select.is_marking) {
        SDL_Point start = image_to_screen(state, 
            state->mark_select.start.x, state->mark_select.start.y);
        SDL_Point current = image_to_screen(state, 
            state->mark_select.current.x, state->mark_select.current.y);
            
        SDL_Rect mark_rect = {
            start.x, start.y,
            current.x - start.x,
            current.y - start.y
        };
        
        SDL_SetRenderDrawColor(renderer, MARK_COLOR_R, MARK_COLOR_G, MARK_COLOR_B, 180);
        SDL_RenderDrawRect(renderer, &mark_rect);
    }
}

char* show_file_dialog(BOOL save) {
    OPENFILENAMEA ofn;
    static char szFile[MAX_PATH] = {0};
    ZeroMemory(&ofn, sizeof(ofn));
    ofn.lStructSize = sizeof(ofn);
    ofn.lpstrFile = szFile;
    ofn.nMaxFile = sizeof(szFile);
    ofn.lpstrFilter = "Images\0*.png;*.jpg;*.jpeg;*.bmp\0All Files\0*.*\0";
    ofn.nFilterIndex = 1;
    ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_NOCHANGEDIR;
    
    if (save) {
        ofn.Flags |= OFN_OVERWRITEPROMPT;
        if (GetSaveFileNameA(&ofn)) return szFile;
    } else {
        if (GetOpenFileNameA(&ofn)) return szFile;
    }
    return NULL;
}

void handle_mouse(SDL_Event* e, AppState* state, SDL_Window* window) {
    int mouse_x, mouse_y;
    SDL_GetMouseState(&mouse_x, &mouse_y);

    if (e->type == SDL_MOUSEBUTTONDOWN) {
        if (e->button.button == SDL_BUTTON_MIDDLE) {
            state->is_dragging_view = true;
            state->drag_start.x = mouse_x - state->view_offset.x;
            state->drag_start.y = mouse_y - state->view_offset.y;
        } 
        else if (e->button.button == SDL_BUTTON_LEFT) {
            if (state->ctrl_pressed) {
                state->mark_select.is_marking = true;
                SDL_Point img_pos = screen_to_image(state, mouse_x, mouse_y);
                state->mark_select.start = img_pos;
                state->mark_select.current = img_pos;
            }
            else if (state->show_crop_edges) {
                SDL_Point left_edge = image_to_screen(state, state->crop_borders.left, 0);
                SDL_Point right_edge = image_to_screen(state, state->crop_borders.right, 0);
                SDL_Point top_edge = image_to_screen(state, 0, state->crop_borders.top);
                SDL_Point bottom_edge = image_to_screen(state, 0, state->crop_borders.bottom);

                int distances[] = {
                    abs(mouse_x - left_edge.x),
                    abs(mouse_x - right_edge.x),
                    abs(mouse_y - top_edge.y),
                    abs(mouse_y - bottom_edge.y)
                };

                state->crop_borders.dragging_edge = 0;
                int min_dist = EDGE_SNAP_RANGE;
                for (int i = 0; i < 4; i++) {
                    if (distances[i] < min_dist) {
                        state->crop_borders.dragging_edge = i + 1;
                        min_dist = distances[i];
                    }
                }

                if (!state->crop_borders.dragging_edge) {
                    SDL_Point img_pos = screen_to_image(state, mouse_x, mouse_y);
                    state->rect_select.dragging_rect = true;
                    state->rect_select.start = img_pos;
                    state->rect_select.current = img_pos;
                }
            }
        }
    }
    else if (e->type == SDL_MOUSEMOTION) {
        if (state->is_dragging_view) {
            state->view_offset.x = mouse_x - state->drag_start.x;
            state->view_offset.y = mouse_y - state->drag_start.y;
        }
        else if (state->rect_select.dragging_rect) {
            SDL_Point img_pos = screen_to_image(state, mouse_x, mouse_y);
            state->rect_select.current = img_pos;
        }
        else if (state->mark_select.is_marking) {
            SDL_Point img_pos = screen_to_image(state, mouse_x, mouse_y);
            state->mark_select.current = img_pos;
        }
        else if (state->crop_borders.dragging_edge) {
            SDL_Point img_pos = screen_to_image(state, mouse_x, mouse_y);
            switch (state->crop_borders.dragging_edge) {
                case 1: state->crop_borders.left = SDL_clamp(img_pos.x, 0, state->crop_borders.right-1); break;
                case 2: state->crop_borders.right = SDL_clamp(img_pos.x, state->crop_borders.left+1, state->width); break;
                case 3: state->crop_borders.top = SDL_clamp(img_pos.y, 0, state->crop_borders.bottom-1); break;
                case 4: state->crop_borders.bottom = SDL_clamp(img_pos.y, state->crop_borders.top+1, state->height); break;
            }
            state->modified = true;
        }
    }
    else if (e->type == SDL_MOUSEBUTTONUP) {
        if (state->rect_select.dragging_rect) {
            SDL_Point start = state->rect_select.start;
            SDL_Point current = state->rect_select.current;
            
            state->crop_borders.left = SDL_min(start.x, current.x);
            state->crop_borders.right = SDL_max(start.x, current.x);
            state->crop_borders.top = SDL_min(start.y, current.y);
            state->crop_borders.bottom = SDL_max(start.y, current.y);
            
            state->crop_borders.left = SDL_clamp(state->crop_borders.left, 0, state->width-1);
            state->crop_borders.right = SDL_clamp(state->crop_borders.right, state->crop_borders.left+1, state->width);
            state->crop_borders.top = SDL_clamp(state->crop_borders.top, 0, state->height-1);
            state->crop_borders.bottom = SDL_clamp(state->crop_borders.bottom, state->crop_borders.top+1, state->height);
            
            state->show_crop_edges = true;
            state->modified = true;
        }
        else if (state->mark_select.is_marking) {
            SDL_Point start = state->mark_select.start;
            SDL_Point current = state->mark_select.current;
            
            SDL_Rect new_mark = {
                SDL_min(start.x, current.x),
                SDL_min(start.y, current.y),
                abs(current.x - start.x),
                abs(current.y - start.y)
            };
            
            new_mark.x = SDL_clamp(new_mark.x, 0, state->width-1);
            new_mark.y = SDL_clamp(new_mark.y, 0, state->height-1);
            new_mark.w = SDL_clamp(new_mark.w, 1, state->width - new_mark.x);
            new_mark.h = SDL_clamp(new_mark.h, 1, state->height - new_mark.y);
            
            if (new_mark.w > 5 && new_mark.h > 5) {
                state->marked_areas = (MarkedArea*)realloc(state->marked_areas, 
                    (state->marked_area_count + 1) * sizeof(MarkedArea));
                state->marked_areas[state->marked_area_count].rect = new_mark;
                state->marked_area_count++;
                state->modified = true;
            }
        }
        
        state->is_dragging_view = false;
        state->rect_select.dragging_rect = false;
        state->mark_select.is_marking = false;
        state->crop_borders.dragging_edge = 0;
    }
    else if (e->type == SDL_MOUSEWHEEL) {
        SDL_Point mouse_before = screen_to_image(state, mouse_x, mouse_y);
        
        if (e->wheel.y > 0) state->zoom_factor *= 1.1;
        else if (e->wheel.y < 0) state->zoom_factor *= 0.9;
        
        state->zoom_factor = SDL_clamp(state->zoom_factor, 0.1, 10.0);
        calculate_image_position(state, window);
        
        SDL_Point mouse_after = screen_to_image(state, mouse_x, mouse_y);
        state->view_offset.x += (mouse_before.x - mouse_after.x) * state->scale_factor * state->zoom_factor;
        state->view_offset.y += (mouse_before.y - mouse_after.y) * state->scale_factor * state->zoom_factor;
    }
}

void toggle_fullscreen(SDL_Window* window, AppState* state) {
    state->is_fullscreen = !state->is_fullscreen;
    SDL_SetWindowFullscreen(window, state->is_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0);
    
    for(int i=0; i<3; i++){
        SDL_PumpEvents();
        SDL_Delay(20);
        calculate_image_position(state, window);
    }
}

void load_current_image(AppState* state, SDL_Renderer* renderer, SDL_Window* window) {
    if (state->file_count == 0 || state->current_index >= state->file_count) return;

    char path[MAX_PATH];
    sprintf(path, "%s\\%s", state->current_dir, state->file_list[state->current_index]);
    
    SDL_DestroyTexture(state->texture);
    stbi_image_free(state->image_data);
    clear_marked_areas(state);
    
    state->texture = load_image(renderer, path, &state->width, &state->height, &state->image_data);
    if (state->texture) {
        strcpy(state->current_file, path);
        state->crop_borders = (CropBorders){0, state->width, 0, state->height, 0};
        state->zoom_factor = 1.0;
        state->view_offset = (SDL_Point){0, 0};
        
        if (!state->lock_crop_display) {
            state->show_crop_edges = false;
        }
        
        calculate_image_position(state, window);
    }
}

void load_next_image(AppState* state, SDL_Renderer* renderer, SDL_Window* window, int direction) {
    if (state->file_count == 0) return;

    state->current_index = (state->current_index + direction + state->file_count) % state->file_count;
    load_current_image(state, renderer, window);
}

int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) {
    setlocale(LC_ALL, ".UTF-8");

    SDL_Init(SDL_INIT_VIDEO);
    SDL_Window* window = SDL_CreateWindow("简", 
        SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
        WINDOW_WIDTH, WINDOW_HEIGHT, 
        SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI | SDL_WINDOW_HIDDEN);

    SDL_StopTextInput();

    SDL_Renderer* renderer = SDL_CreateRenderer(window, -1, 
        SDL_RENDERER_ACCELERATED | SDL_RENDERER_PRESENTVSYNC);

    AppState state = {0};
    state.zoom_factor = 1.0;
    state.show_crop_edges = false;
    state.lock_crop_display = false;
    state.marked_areas = NULL;
    state.marked_area_count = 0;
    state.mark_select.is_marking = false;
    state.ctrl_pressed = false;
    
    bool running = true;
    bool show_dialog = true;
    bool dialog_shown = false;
    bool window_initialized = false;

    /* 处理命令行参数 */
    int argc;
    LPWSTR* wargv = CommandLineToArgvW(GetCommandLineW(), &argc);
    if (argc >= 2) {
        char filepath[MAX_PATH] = {0};
        WideCharToMultiByte(CP_ACP, 0, wargv[1], -1, filepath, MAX_PATH, NULL, NULL);
        
        if (PathFileExistsA(filepath)) {
            strcpy(state.current_file, filepath);
            get_dir_and_base(filepath, state.current_dir, NULL);
            load_file_list(&state);
            
            state.texture = load_image(renderer, filepath, &state.width, &state.height, &state.image_data);
            if (state.texture) {
                state.crop_borders = (CropBorders){0, state.width, 0, state.height, 0};
                calculate_image_position(&state, window);
                show_dialog = false;
                dialog_shown = true;

                char current_base[MAX_PATH];
                get_dir_and_base(filepath, NULL, current_base);
                for (int i = 0; i < state.file_count; i++) {
                    if (strcmp(state.file_list[i], current_base) == 0) {
                        state.current_index = i;
                        break;
                    }
                }
            }
        }
    }
    LocalFree(wargv);

    SDL_ShowWindow(window);
    window_initialized = true;

    while (running) {
        SDL_Event e;
        while (SDL_PollEvent(&e)) {
            if (e.type == SDL_QUIT) {
                running = false;
                continue;
            }

            if (show_dialog && !dialog_shown && window_initialized) {
                dialog_shown = true;
                char* path = show_file_dialog(FALSE);
                if (path) {
                    strcpy(state.current_file, path);
                    get_dir_and_base(path, state.current_dir, NULL);
                    
                    load_file_list(&state);
                    state.texture = load_image(renderer, path, &state.width, &state.height, &state.image_data);
                    if (state.texture) {
                        state.crop_borders = (CropBorders){0, state.width, 0, state.height, 0};
                        calculate_image_position(&state, window);
                        show_dialog = false;
                    }
                } else {
                    show_dialog = false;
                    running = false;
                    continue;
                }
            }

            if (e.type == SDL_WINDOWEVENT) {
                switch (e.window.event) {
                    case SDL_WINDOWEVENT_SHOWN:
                        continue;
                    case SDL_WINDOWEVENT_SIZE_CHANGED:
                    case SDL_WINDOWEVENT_MAXIMIZED:
                    case SDL_WINDOWEVENT_RESTORED:
                    case SDL_WINDOWEVENT_MOVED:
                    case SDL_WINDOWEVENT_FOCUS_GAINED:
                        if (state.texture) {
                            calculate_image_position(&state, window);
                        }
                        break;
                }
            }

            HWND hwnd = GetActiveWindow();
            HIMC himc = ImmGetContext(hwnd);
            ImmAssociateContext(hwnd, NULL);
            ImmReleaseContext(hwnd, himc);

            if (e.type == SDL_KEYDOWN) {
                SDL_Scancode scan = e.key.keysym.scancode;
                if (scan == SDL_SCANCODE_J) {
                    state.show_crop_edges = !state.show_crop_edges;
                }
                else if (scan == SDL_SCANCODE_L) {
                    state.lock_crop_display = !state.lock_crop_display;
                }
                else if (scan == SDL_SCANCODE_LCTRL || scan == SDL_SCANCODE_RCTRL) {
                    state.ctrl_pressed = true;
                }

                switch (e.key.keysym.sym) {
                    case SDLK_s:
                        if (SDL_GetModState() & KMOD_CTRL) {
                            if (state.marked_area_count > 0) {
                                const SDL_MessageBoxButtonData buttons[] = {
                                    { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "取消" },
                                    { 0, 1, "保存原始" },
                                    { 0, 2, "保存带标记" }
                                };
                                
                                const SDL_MessageBoxData msgbox = {
                                    SDL_MESSAGEBOX_INFORMATION,
                                    NULL,
                                    "保存选项",
                                    "选择保存方式:",
                                    SDL_arraysize(buttons),
                                    buttons,
                                    NULL
                                };
                                
                                int button_id;
                                if (SDL_ShowMessageBox(&msgbox, &button_id) == 0) {
                                    if (button_id > 0) {
                                        char* path = show_file_dialog(TRUE);
                                        if (path) {
                                            save_cropped_image(&state, path, renderer, window, button_id == 2);
                                        }
                                    }
                                }
                            } else {
                                char* path = show_file_dialog(TRUE);
                                if (path) {
                                    save_cropped_image(&state, path, renderer, window, false);
                                }
                            }
                        }
                        break;
                    case SDLK_F11: 
                        toggle_fullscreen(window, &state); 
                        break;
                    case SDLK_ESCAPE: 
                        running = false; 
                        break;
                    case SDLK_LEFT: 
                        load_next_image(&state, renderer, window, -1); 
                        break;
                    case SDLK_RIGHT: 
                        load_next_image(&state, renderer, window, 1); 
                        break;
                    case SDLK_DELETE:
                        if (state.texture) {
                            const SDL_MessageBoxButtonData buttons[] = {
                                { SDL_MESSAGEBOX_BUTTON_ESCAPEKEY_DEFAULT, 0, "取消" },
                                { SDL_MESSAGEBOX_BUTTON_RETURNKEY_DEFAULT, 1, "删除" }
                            };

                            const SDL_MessageBoxData msgbox = {
                                SDL_MESSAGEBOX_WARNING,
                                NULL,
                                "删除文件",
                                "确定要永久删除此文件吗？",
                                SDL_arraysize(buttons),
                                buttons,
                                NULL
                            };

                            int button_id;
                            if (SDL_ShowMessageBox(&msgbox, &button_id) == 0) {
                                if (button_id == 1) {
                                    if (DeleteFileA(state.current_file)) {
                                        load_file_list(&state);
                                        
                                        if (state.file_count > 0) {
                                            if (state.current_index >= state.file_count) {
                                                state.current_index = state.file_count - 1;
                                            }
                                            load_current_image(&state, renderer, window);
                                        } else {
                                            SDL_DestroyTexture(state.texture);
                                            stbi_image_free(state.image_data);
                                            state.texture = NULL;
                                            state.image_data = NULL;
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    case SDLK_SPACE: 
                        state.zoom_factor = 1.0;
                        state.view_offset = (SDL_Point){0, 0};
                        calculate_image_position(&state, window);
                        break;
                    case SDLK_c:
                        if (SDL_GetModState() & KMOD_CTRL) {
                            clear_marked_areas(&state);
                            state.modified = true;
                        }
                        break;
                }

                if (SDL_GetModState() & KMOD_CTRL) {
                    switch (e.key.keysym.sym) {
                        case SDLK_z: // Ctrl+Z 逆时针旋转
                            rotate_image(&state, renderer, 270);
                            calculate_image_position(&state, window);
                            break;
                        case SDLK_y: // Ctrl+Y 顺时针旋转
                            rotate_image(&state, renderer, 90);
                            calculate_image_position(&state, window);
                            break;
                    }
                }
            }
            else if (e.type == SDL_KEYUP) {
                if (e.key.keysym.scancode == SDL_SCANCODE_LCTRL || 
                    e.key.keysym.scancode == SDL_SCANCODE_RCTRL) {
                    state.ctrl_pressed = false;
                }
            }

            if (state.texture) {
                handle_mouse(&e, &state, window);
            }
        }

        SDL_SetRenderDrawColor(renderer, 30, 30, 30, 255);
        SDL_RenderClear(renderer);

        if (state.texture) {
            int render_w, render_h;
            SDL_GL_GetDrawableSize(window, &render_w, &render_h);
            
            SDL_Rect dst = {
                (render_w - state.img_dst_rect.w)/2 + state.view_offset.x,
                (render_h - state.img_dst_rect.h)/2 + state.view_offset.y,
                state.img_dst_rect.w,
                state.img_dst_rect.h
            };
            
            SDL_RenderCopyEx(renderer, state.texture, NULL, &dst, 
                            0, NULL, SDL_FLIP_NONE);
            render_crop_edges(renderer, &state);
            render_marked_areas(renderer, &state);
        }

        SDL_RenderPresent(renderer);
    }

    if (state.texture) SDL_DestroyTexture(state.texture);
    if (state.image_data) stbi_image_free(state.image_data);
    if (state.file_list) {
        for (int i = 0; i < state.file_count; i++) {
            free(state.file_list[i]);
        }
        free(state.file_list);
    }
    clear_marked_areas(&state);
    SDL_DestroyRenderer(renderer);
    SDL_DestroyWindow(window);
    SDL_Quit();
    return 0;
}